package com.biannuo.szk.gateway.filter;

import org.springframework.cloud.gateway.filter.GatewayFilter;
import org.springframework.cloud.gateway.filter.GatewayFilterChain;
import org.springframework.cloud.gateway.filter.factory.AbstractGatewayFilterFactory;
import org.springframework.core.io.buffer.DataBuffer;
import org.springframework.http.HttpStatus;
import org.springframework.stereotype.Component;
import org.springframework.web.server.ServerWebExchange;
import reactor.core.publisher.Flux;
import reactor.core.publisher.Mono;

import java.nio.charset.StandardCharsets;
import java.util.Arrays;
import java.util.List;

/**
 * 自定义局部过滤器
 * 只允许查询id为minId- maxId之间的用户
 *
 * @author szk
 */
//@Component
public class UserGatewayFilterFactory extends AbstractGatewayFilterFactory<UserGatewayFilterFactory.Config> {
    /**
     * 对象属性
     */
    public static final String[] KEY_ARRAY = {"minId", "maxId"};

    public UserGatewayFilterFactory() { //构造函数
        super(Config.class);
    }

    @Override
    public List<String> shortcutFieldOrder() { // 读取配置文件内容，赋值到配置类属性
        return Arrays.asList(KEY_ARRAY);
    }

    /**
     * 过滤器逻辑
     *
     * @param config
     * @return
     */
    @Override
    public GatewayFilter apply(Config config) {
        return new GatewayFilter() {
            @Override
            public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
                // 得到id参数的值
                String id = exchange.getRequest().getQueryParams().getFirst("id");
                if (null != id) {
                    int numberId = Integer.parseInt(id);
                    // 判断id是否大于最小值 并且 小于最大值
                    if (numberId > config.getMinId() && numberId < config.getMaxId()) {
                        // 放行
                        return chain.filter(exchange);
                    }
                }
                //友好提示
                byte[] bytes = ("您不能访问" + id + "用户的数据").getBytes(StandardCharsets.UTF_8);
                DataBuffer wrap = exchange.getResponse().bufferFactory().wrap(bytes);
                // 标记为不能访问的状态码
                exchange.getResponse().setStatusCode(HttpStatus.NOT_ACCEPTABLE);
                // 返回友好提示
                return exchange.getResponse().writeWith(Flux.just(wrap));
            }
        };
    }

    /**
     * 配置类，接收配置文件的值
     */
    public static class Config {
        // 最小支持查询的id
        private Integer minId;
        // 最大支持查询的id
        private Integer maxId;

        public void setMinId(Integer minId) {
            this.minId = minId;
        }

        public void setMaxId(Integer maxId) {
            this.maxId = maxId;
        }

        public Integer getMinId() {
            return minId;
        }

        public Integer getMaxId() {
            return maxId;
        }
    }
}
